package cn.simple.http;

import cn.hutool.core.lang.TypeReference;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import lombok.Data;

import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

@Data
public class HttpRequest {

    private final String method;

    private final String url;

    private final Map<String, String> headers;

    private byte[] content;

    private JSONObject config;

    public HttpRequest(String method, String url) {
        this.method = method;
        this.url = url;
        this.headers = new HashMap<>();
    }

    public HttpResponse execute() {
        cn.hutool.http.HttpRequest request = this.createRequest();
        request.body(content);

        Map<String, String> headers = this.getRealHeaders();
        for (Map.Entry<String, String> entry : headers.entrySet()) {
            request.header(entry.getKey(), entry.getValue());
        }
        return request.execute();
    }

    private cn.hutool.http.HttpRequest createRequest() {
        String url = this.getRealUrl();
        if ("GET".equals(this.method)) {
            return HttpUtil.createGet(url);
        } else {
            return HttpUtil.createPost(url);
        }
    }

    public void setContent(String content) {
        if (content != null) {
            this.content = content.getBytes(StandardCharsets.UTF_8);
        }
    }

    public String getRealUrl() {
        if (!this.url.startsWith("http")) {
            String host = this.config.getStr("HOST");
            if (host != null) {
                return host + this.url;
            }
        }
        return this.url;
    }

    public void addHeader(String key, String value) {
        this.headers.put(key, value);
    }

    private Map<String, String> getGlobalHeader() {
        try {
            return Optional.ofNullable(this.config.getJSONObject("headers"))
                    .map(o -> o.toBean(new TypeReference<Map<String, String>>() {
                    }))
                    .orElse(Collections.emptyMap());
        } catch (Exception e) {
            return Collections.emptyMap();
        }
    }

    public Map<String, String> getRealHeaders() {
        Map<String, String> headers = new HashMap<>();
        headers.putAll(this.getGlobalHeader());
        headers.putAll(this.headers);
        return headers;
    }
}
